use crate::Byte;

/// 6502 状态寄存器标志位
/// 
/// 7 6 5 4 3 2 1 0
/// N V _ B D I Z C
/// 
/// - N: Negative
/// - V: Overflow
/// - _: Unused (always 1)
/// - B: Break
/// - D: Decimal
/// - I: Interrupt Disable
/// - Z: Zero
/// - C: Carry
#[derive(Debug, Clone, Copy, Default)]
pub struct StatusRegister {
    pub value: Byte,
}

impl StatusRegister {
    pub const CARRY: Byte = 0b0000_0001;
    pub const ZERO: Byte = 0b0000_0010;
    pub const INTERRUPT_DISABLE: Byte = 0b0000_0100;
    pub const DECIMAL: Byte = 0b0000_1000;
    pub const BREAK: Byte = 0b0001_0000;
    pub const UNUSED: Byte = 0b0010_0000;
    pub const OVERFLOW: Byte = 0b0100_0000;
    pub const NEGATIVE: Byte = 0b1000_0000;

    pub fn new() -> Self {
        StatusRegister {
            value: Self::UNUSED, // 未使用位始终为1
        }
    }

    pub fn set(&mut self, flag: Byte, set: bool) {
        if set {
            self.value |= flag;
        } else {
            self.value &= !flag;
        }
        // 确保未使用位始终为1
        self.value |= Self::UNUSED;
    }

    pub fn get(&self, flag: Byte) -> bool {
        (self.value & flag) != 0
    }

    pub fn update_zero_negative(&mut self, value: Byte) {
        self.set(Self::ZERO, value == 0);
        self.set(Self::NEGATIVE, (value & Self::NEGATIVE) != 0);
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_status_register() {
        let mut status = StatusRegister::new();
        
        // 测试初始状态
        assert!(status.get(StatusRegister::UNUSED));
        
        // 测试设置和获取标志位
        status.set(StatusRegister::CARRY, true);
        assert!(status.get(StatusRegister::CARRY));
        
        status.set(StatusRegister::CARRY, false);
        assert!(!status.get(StatusRegister::CARRY));
        
        // 测试零和负标志位更新
        status.update_zero_negative(0);
        assert!(status.get(StatusRegister::ZERO));
        assert!(!status.get(StatusRegister::NEGATIVE));
        
        status.update_zero_negative(0x80);
        assert!(!status.get(StatusRegister::ZERO));
        assert!(status.get(StatusRegister::NEGATIVE));
    }
}